<!DOCTYPE html>
<html lang="en">
<head>
    <title>囧么肥事</title>
    <meta charset="UTF-8"/>
    <meta name="viewport"
          content="width=device-width,height=device-height,initial-scale=1.0,maximum-scale=1.0,user-scalable=0"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta http-equiv="Content-Type" content="text/html;"/>
    <meta name="renderer" content="webkit">
    <!--解决页面加载网络图片的403问题 , 可以让img标签预加载网络图片-->
    <meta name="referrer" content="no-referrer" />

    <!--markdown S -->
    <link rel="stylesheet" type="text/css" href="../../static/css/export_setting_css.css"/>
    <link rel="stylesheet" type="text/css" href="../../static/css/markdown_preview_css.css"/>
    <!--markdown E -->

    <!--left bar tools css E-->
    <link rel="stylesheet" type="text/css" href="../../static/css/nav.css">
    <link rel="stylesheet" type="text/css" href="http://www.jq22.com/jquery/font-awesome.4.6.0.css">
    <!--left bar tools css E-->

    <!-- 滚动条 S -->
    <link rel="stylesheet" href="../../static/css/optiscroll.css">
    <!-- 滚动条 E -->
</head>
<body>
<div id="m-wrapper" class="m-wrapper optiscroll">
    <!-- top 锚点 -->
    <a id="top"></a>

    <!-- left bar tools S -->
    <div class="leftNav-item">
        <ul>
            <li>
                <i class="fa fa-location-arrow"></i>
                <a href="http://jiongmefeishi.gitee.io/monster-blog/" target="_blank" class="rota">个人网站</a>
            </li>

            <li title="Git">
                <i class="fa fa-code-fork" aria-hidden="true"></i>
                <a href="http://jiongmefeishi.gitee.io/monster-blog/" target="_blank" class="rota">Git Page</a>
            </li>

            <li lay-data="img" data-fooc="http://resource.zqtaotao.cn/wx/qrcode/jiongmefeishi.jpg">
                <i class="fa fa-comments-o"></i><a href="javascript:;" class="rota">公众号</a>
            </li>

            <li lay-data="img" data-fooc="http://resource.zqtaotao.cn/weixincode.png">
                <i class="fa fa-money"></i><a href="javascript:;" class="rota">小额打赏</a>
            </li>
            <li title="返回顶部" class="for-top">
                <i class="fa fa-arrow-up"></i>
                <a href="#top" class="rota">去顶部</a>
            </li>
        </ul>
    </div>
    <!-- left bar tools E -->

    <!--content S-->

    <div id="export_content"><div class="output_wrapper" id="output_wrapper_id"><h1 id="hmysql"><span>《MySQL面试小抄》索引考点一面总结</span></h1>
        <p>我是肥哥，一名不专业的面试官！</p>
        <p>我是囧囧，一名积极找工作的小菜鸟，<strong>囧囧表示：面试最怕的就是面试官问的知识点太笼统，自己无法快速定位到关键问题点！！！</strong></p>
        <hr>
        <p>本期主要面试考点</p>
        <pre><code class="hljs">面试官考点之谈谈你对索引的理解？<br></code></pre>
        <pre><code class="hljs">面试官考点之解释一下计算机层面索引快的原因？<br></code></pre>
        <pre><code class="hljs">面试官考点之为什么不使用哈希结构作为索引结构？<br></code></pre>
        <pre><code class="hljs">面试官考点之为什么不使用二叉树作为索引结构？<br></code></pre>
        <pre><code class="hljs">面试官考点之为什么不使用B-Tree，而是B+Tree？<br></code></pre>
        <pre><code class="hljs">面试官考点之索引是加速查询，那么是否应该给表尽可能建立多的索引列？<br></code></pre>
        <hr>
        <figure><img src="http://resource.zqtaotao.cn/wx/21/%E7%B4%A2%E5%BC%95%E5%B0%8F%E6%8A%84%E4%B8%80%E9%9D%A2.png" alt="索引小抄一面对话" title="索引小抄一面对话"><figcaption>索引小抄一面对话</figcaption></figure>
        <hr>
        <h3 id="h"><span>面试官考点之谈谈你对索引的理解？</span></h3>
        <p>谈到索引，最先联想到的大概就是字典目录，根据MySQL官方定义，索引是用来帮助MySQL<strong>高效获取数据</strong>的一种数据结构。</p>
        <p>本质上：索引是一种有序的快速查找的数据结构，用来快速高效的查找数据。</p>
        <p>简单来说，可以类比字典目录，火车车次表。</p>
        <h3 id="h-1"><span>面试官考点之解释一下计算机层面索引快的原因？</span></h3>
        <p>计算机从磁盘获取数据，加载到内存期间，一般都要经历3个常规的<strong>耗时过程</strong>：</p>
        <p>1、寻道（时间）：确定要读的数据在哪个磁道耗费的时间<br>2、旋转延迟（时间）：确定要读的数据在磁道上的哪个扇区耗费的时间<br>3、数据传输（时间）：数据加载到内存耗费的时间</p>
        <p>每次加载数据，我们称其为一次磁盘IO，每一次IO操作耗费时间 = 寻道 + 旋转延迟 + 数据传输（时间短暂，可以忽略不计）。</p>
        <p>事实上实际加载数据到内存的时间非常短暂，一次IO操作主要的耗时来自寻道和旋转延迟。</p>
        <p>总体来说，一般一次IO操作，耗时大概只有几ms。假如是4ms，虽然看起来很短暂，但是数据库百万级别的数据加载一遍，就需要4000s，对于一个系统来说，简直是毁灭级别的。</p>
        <p>我们需要的就是减少磁盘IO的次数，这也是使用索引的意义所在！！！索引能够保证在<strong>亿级别的数据，只需要2~4次磁盘IO</strong>，这无疑是个福音！</p>
        <h3 id="h-2"><span>面试官考点之为什么不使用哈希结构作为索引结构？</span></h3>
        <p>一般正常的业务场景中，通常查询多数是范围查询 类似：</p>
        <pre><code class="mysql language-mysql">select&nbsp;id,&nbsp;name,&nbsp;age&nbsp;from&nbsp;sys_user&nbsp;where&nbsp;age&nbsp;between&nbsp;18&nbsp;and&nbsp;28;<br></code></pre>
        <p>哈希结构作为索引，那么存储引擎就会为每一行表记录计算出哈希值，哈希索引存储的就是HASH码；</p>
        <p>HASH码直接随机生成，并没有规律</p>
        <p>没有规律的HASH码，导致数据<strong>随机分布存储</strong>，这就导致即使是两个很相近的行记录，极大可能也会被分配到不同的桶（磁盘块）中。</p>
        <p>最坏的情况下每查找一条记录，都要进行一次磁盘IO （可怕）。</p>
        <p>优点，哈希结构这样key-val 键值对的形式对于精确查找非常敏感，对全值匹配很友好，所以单条记录查询效率非常高，时间复杂度为 1，但是我们日常业务来说，最常用的还是范围搜索，所以不哈希结构适合。</p>
        <p>记住一点即可：<strong>Hash索引适合精确查找，全值匹配，不适合范围查找。</strong></p>
        <p>MySQL目前有Memory引擎和NDB引擎支持Hash索引。</p>
        <h3 id="h-3"><span>面试官考点之为什么不使用二叉树作为索引结构？</span></h3>
        <p>首先观察一下二叉树结构</p>
        <figure><img src="http://resource.zqtaotao.cn/wx/21/0420/%E4%BA%8C%E5%8F%89%E6%A0%91.png" alt="二叉树" title="二叉树"><figcaption>二叉树</figcaption></figure>
        <p>二叉树最多有两个子节点，这种结构导致树的高度会很高，增加IO次数，<strong>特殊情况下可能化为链表结构</strong>，相当于全表扫描，全量磁盘IO。</p>
        <p>假设二叉树结构作为索引，理想情况下是一颗完全二叉树，那么具有n个节点的完全二叉树深度为log2x+1</p>
        <p>（其中x表示不大于n的最大整数）</p>
        <p>如果一个数据在二叉树结构的100层，那么为了查找到此数据，需要进行100次磁盘IO。更糟糕情况下，二叉树会退化成链表结构，既，斜二叉树。</p>
        <figure><img src="http://resource.zqtaotao.cn/wx/21/%E6%96%9C%E4%BA%8C%E5%8F%89%E6%A0%91.png" alt="斜二叉树" title="斜二叉树"><figcaption>斜二叉树</figcaption></figure>
        <p>类似的平衡二叉树，高度也很高。</p>
        <h3 id="hbtreebtree"><span>面试官考点之为什么不使用B-Tree，而是B+Tree？</span></h3>
        <p>既然二叉树结构树高度很高，导致查询时磁盘IO增加，那B-Tree 呢？B-Tree可以存储更多的数据，高度更低，为什么不选择？而是B+Tree？</p>
        <p>B-Tree是多路平衡搜索树，相比二叉树结构，可以极大的优化磁盘IO次数，但是<strong>B-Tree每个节点中不仅包含数据的key（索引值），还有data（整行记录）</strong>，使用B-Tree结构，优点是找到索引就代表找到了数据记录。</p>
        <p>既然如此为什么不使用B-Tree结构？还是老问题，磁盘IO数！！！</p>
        <p>我们知道MySQL读取数据是以<strong>页为单位</strong>（磁盘块），每页（或者说每个磁盘块）的存储空间是有限的</p>
        <p>如果data 很大，将会导致每页存储的索引数量很小</p>
        <p>所以数据表存储的数据量很大的时候同样会导致 B-Tree的深度很大，增大查询时的磁盘I/O次数，进而影响查询效率。</p>
        <p>再说到B+Tree，B+Tree是对B-Tree 的一种优化结构，使其更适合实现外存储索引结构</p>
        <pre><code class="hljs">1、非叶子节点只存储键值信息(索引信息)<br><br>2、所有的数据记录都按照键值大小顺序存放在同一层的叶子节点上<br></code></pre>
        <p><strong>好处</strong>：B+Tree的非叶子节点只存储键值信息，那么每一页能存储更多的索引，树的高度被压缩到很低，磁盘IO次数更小，一般情况下2~4次IO，即可查询到想要的记录。</p>
        <p>而且因为表数据都是顺序存储在B+Tree结构的叶子节点，所以对于<strong>范围查找很友好</strong>，效率高！</p>
        <h3 id="h-4"><span>面试官考点之索引是加速查询，那么是否应该给表尽可能建立多的索引列？</span></h3>
        <p>虽然索引的优势是加快查询效率，减少磁盘IO次数，但是盲目创建过多索引，大大增加了维护索引的时间成本和空间成本。</p>
        <p>首先说一下索引的好处</p>
        <pre><code class="hljs">1、减少IO次数，提高-检索效率<br><br>2、降低数据排序成本，可以减少CPU消耗<br></code></pre>
        <p><strong>时间成本</strong></p>
        <p>因为索引是有序的快速查找结构，要维护索引的这个快速查找且有序特性，需要不断的进行调整，而调整就需要时间成本。</p>
        <p>创建索引和维护索引要耗费时间，当对表中的数据进行增加、删除和修改的时候，索引也要动态地维护，这样就降低了数据的维护速度。</p>
        <p>而且这种时间成本随着数据量的增加而增加！</p>
        <p><strong>空间成本</strong></p>
        <p>其次，每一个索引都是一棵B+Tree，保存索引和指向实体表的引用，需要占据空间。</p>
        <p>如果建立的是<strong>聚簇索引，数据和主键都保存在索引文件</strong>中，则需要更大的空间成本。</p>
        <p>阅读原文：</p>
        <p><a href="https://mp.weixin.qq.com/s/2jC8AwsH8cpk8T23tN0bgg">《MySQL面试小抄》索引考点二面总结</a></p>
        <p><a href="https://mp.weixin.qq.com/s/TMa6PT070inUtURl48URuQ">《MySQL面试小抄》索引考点一面总结</a></p>
        <p>随缘更新，整理不易，欢迎联系小白讨论，大神巴巴请绕路！</p>
        <p>更多精彩内容，欢迎关注微信公众号：<strong>囧么肥事</strong> (或搜索：jiongmefeishi)</p>
        <figure><img src="https://img-blog.csdnimg.cn/img_convert/cb3a296f8edbcc70370d4eb569c40634.png" alt="囧么肥事" title="囧么肥事"><figcaption>囧么肥事</figcaption></figure></div></div>

    <!--content E-->
</div>



</body>
<!--left bar tools js S-->
<script src="http://www.jq22.com/jquery/jquery-1.10.2.js"></script>
<script type="text/javascript" src="../../static/js/nav.js"></script>
<!--left bar tools js E-->

<!-- 滚动条 S -->
<script type="text/javascript" src="../../static/js/optiscroll.js"></script>
<!-- 滚动条 E -->

<!--commonjs S-->
<script type="text/javascript" src="../../static/js/common.js"></script>
<!--commonjs E-->

</html>
